﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace Project
{
    public class Client
    {
        IPEndPoint ip;
        Socket server;
        public Client()
        {
            ip = new IPEndPoint(IPAddress.Parse("128.143.69.241"), 9091);
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        /// <summary>
        /// WARNING:  This is a BLOCKING method and will NOT return until a server request is received.
        /// </summary>
        /// <returns></returns>
        public string getLogCount()
        {
            ip = new IPEndPoint(IPAddress.Parse("128.143.69.241"), 9091);
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                server.Connect(ip);
            }
            catch (SocketException)
            {
                Console.WriteLine("Unable to connect to server.");
                return "Unable to connect";
            }

            server.Send(Encoding.ASCII.GetBytes("GetLogCount\r\n"));
            byte[] data = new byte[1024];
            int receivedDataLength = server.Receive(data);
            string stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
            Console.WriteLine(stringData);

            server.Shutdown(SocketShutdown.Both);
            server.Close();
            return stringData;
        }


        private delegate void AsyncGetHighScoreDel(out HighScore hs);
        /// <summary>
        /// Asynchronous method to retrieve the high score.
        /// </summary>
        /// <param name="level"></param>
        /// <param name="?"></param>
        public void getHighScoreAsync(int level, out HighScore hs) {
            AsyncGetHighScoreDel getHSAsync = delegate(out HighScore highScore) 
            {
                highScore = getHighScore(level);
            };
            getHSAsync.BeginInvoke(out hs, null, null);
        }

        /// <summary>
        /// WARNING:  This is a BLOCKING method and will NOT return until a response is received from the high-score server.
        /// </summary>
        /// <param name="level"></param>
        /// <returns></returns>
        public HighScore getHighScore(int level)
        {
            ip = new IPEndPoint(IPAddress.Parse("128.143.69.241"), 9091);
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                server.Connect(ip);
            }
            catch (SocketException)
            {
                Console.WriteLine("Unable to connect to server.");
                return new HighScore(level, "No conncetion", 0);
            }
            server.Send(Encoding.ASCII.GetBytes("getHighScore " + level + " \r\n"));
            byte[] data = new byte[1024];
            int receivedDataLength = server.Receive(data);
            
            //string stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
            string stringData = Encoding.UTF8.GetString(data, 0, receivedDataLength);
            Console.WriteLine(stringData);

            server.Shutdown(SocketShutdown.Both);
            server.Close();
            //right now output is [name]*[score]
            string[] sarray = stringData.Split(' ');
            return new HighScore(level, sarray[0], Int16.Parse(sarray[1]));
        }

        private delegate void AsyncSendHighScoreDel(HighScore hs);
        /// <summary>
        /// Asynchronous method to retrieve the high score.
        /// </summary>
        /// <param name="level"></param>
        /// <param name="?"></param>
        public void sendHighScoreAsync(HighScore hs) {
            AsyncSendHighScoreDel sendHSAsync = delegate(HighScore highScore) 
            {
                sendHighScore(highScore);
            };
            sendHSAsync.BeginInvoke(hs, null, null);
        }

        /// <summary>
        /// WARNING:  This is a BLOCKING method and will NOT return until a response is received from the high-score server.
        /// </summary>
        /// <param name="hs"></param>
        /// <returns></returns>
        public Boolean sendHighScore(HighScore hs)
        {
            ip = new IPEndPoint(IPAddress.Parse("128.143.69.241"), 9091);
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                server.Connect(ip);
            }
            catch (SocketException)
            {
                Console.WriteLine("Unable to connect to server.");
                //return "Unable to connect";
                return false;
            }
            try
            {
                server.Send(Encoding.ASCII.GetBytes("sendHighScore " + hs.level + " " + hs.username + " " + hs.score + " \r\n"));
            }
            catch (SocketException)
            {
                Console.WriteLine("Error:  Unable to send high score.");
                return false;
            }
            byte[] data = new byte[1024];
            //int receivedDataLength = server.Receive(data);
            //string stringData = Encoding.ASCII.GetString(data, 0, receivedDataLength);
            //string stringData = Encoding.UTF8.GetString(data, 0, receivedDataLength);
            //Console.WriteLine(stringData);

            server.Shutdown(SocketShutdown.Both);
            server.Close();
            return true;
        }
    }
    public struct HighScore
    {
        public int level;
        public string username;
        /// <summary>
        /// The number of points.  0 indicates an invalid score.
        /// </summary>
        public long score;
        public HighScore(int level, string username, long score)
        {
            this.level = level;
            this.username = username;
            this.score = score;
        }
    }
}
